package com.john.elasticsearch.common;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.john.elasticsearch.annotation.Callback.ParameterCallback;
import com.john.elasticsearch.annotation.Parameter;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * 动态封装查询参数
 */
public class Utils<T> {
    /**
     * 获取查询条件
     * @param object 参数对象
     * @return
     */
    public static BoolQueryBuilder getBoolQueryBuilder(Object object){
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        try {
            if(object != null){  //如果条件实体不为null 则执行条件查询
                JSONObject jsonObject = (JSONObject) JSON.toJSON(object);
                Utils.getParameter(object, (key, conType, value,from,to) -> {
                    if(conType.getConType().equals(ConType.EQ.getConType()) && !value.equals("")){ //eq    must 相当于 与 & =
                        boolQueryBuilder.must(QueryBuilders.matchPhraseQuery(key, jsonObject.get(key)));
                    }else if(conType.getConType().equals(ConType.NOTEQ.getConType()) && !value.equals("")){    // must not 相当于 非 ~   ！=
                        boolQueryBuilder.mustNot(QueryBuilders.matchPhraseQuery(key, jsonObject.get(key)));
                    }else if(conType.getConType().equals(ConType.LIKE.getConType()) && !value.equals("")){
                        // 模糊查询
                        boolQueryBuilder.filter(QueryBuilders.wildcardQuery(key+".keyword", "*"+jsonObject.get(key)+"*"));
                    }else if(conType.getConType().equals(ConType.BETWEEN.getConType())  && !value.equals("")){
                        // 范围查询 from:相当于闭区间; gt:相当于开区间(>) gte:相当于闭区间 (>=) lt:开区间(<) lte:闭区间 (<=)
                        boolQueryBuilder.filter(QueryBuilders.rangeQuery(key).from(from).to(to));
                    }
                });
            }
        }catch (Exception ex){
            ex.printStackTrace();
        }
        return boolQueryBuilder;
    }

    /**
     * 获取注解参数
     * @param t 实体类
     * @param ParameterCallback 回调接口
     */
    public static void getParameter(Object t, ParameterCallback ParameterCallback){
        try {
            // 有数据时才处理 得到类的所有field.
            Field[] allFields = t.getClass().getDeclaredFields();
            // 定义一个map用于存放列的序号和field.
            Map<Integer, Field> fieldsMap = new HashMap<Integer, Field>();
            for (int col = 0; col < allFields.length; col++)
            {
                Field field = allFields[col];
                Parameter attr = field.getAnnotation(Parameter.class);
                if (attr != null)
                {
                    // 设置类的私有字段属性可访问.
                    field.setAccessible(true);
                    String attrName = field.getName();
                    Object attrValue = getFieldValueByName(attrName,t);
                    attrValue = attrValue == null ? "" : attrValue;
                    ParameterCallback.paramet(attrName,attr.type(),attrValue.toString(),attr.from(),attr.to());
                }
            }
        }catch (Exception ex){
            ex.printStackTrace();
        }
    }

    /**
     * 根据属性名获取属性值
     * */
    private static Object getFieldValueByName(String fieldName, Object o) {
        try {
            String firstLetter = fieldName.substring(0, 1).toUpperCase();
            String getter = "get" + firstLetter + fieldName.substring(1);
            Method method = o.getClass().getMethod(getter, new Class[] {});
            Object value = method.invoke(o, new Object[] {});
            return value;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}
